package cn.xshi.oauth.client.timer;

import cn.hutool.core.collection.CollectionUtil;
import cn.xshi.common.base.BaseResult;
import cn.xshi.common.util.RestTemplateUtil;
import cn.xshi.common.util.StringUtil;
import cn.xshi.oauth.client.config.OauthClientConfig;
import cn.xshi.oauth.client.publisher.NettyClient;
import cn.xshi.oauth.client.util.HeartbeatAttributesUtil;
import cn.xshi.oauth.client.vo.ChannelEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Desc 建立心跳
 * @Author 邓纯杰
 * @CreateTime 2012-12-12 12:12:12
 */
@Component
@Slf4j
public class HeartbeatScheduled {

    private static final String XSHI_CLOUD_OAUTH = "xshi-cloud-oauth";

    @Resource
    RestTemplateUtil restTemplateUtil;

    @Resource
    HeartbeatAttributesUtil heartbeatAttributesUtil;

    @Resource
    DiscoveryClient discoveryClient;

    @Resource
    OauthClientConfig oauthClientConfig;

    @Resource
    private NettyClient nettyClient;

    public boolean complete = true;//线程处理是否完成 false未完成 ture完成

    /**
     * 建立Token Server心跳
     */
    @Scheduled(cron="*/10 * * * * *")
    public void execute() {
        if(complete){
            try {
                complete = false;
                setOauthServerAddressList();//定时更改
                BaseResult baseResult =  restTemplateUtil.get(restTemplateUtil.restOauthURL()+"/heartbeat",BaseResult.class,null);
                if(null == baseResult || !baseResult.getSuccess()){
                    log.error("...");
                    heartbeatAttributesUtil.setConnected(false);
                    return;
                }
                heartbeatAttributesUtil.setConnected(true);
                log.info("连接授权中心成功...");
            }catch (Exception e){
                heartbeatAttributesUtil.setConnected(false);
                log.error("连接授权中心异常，异常信息：",e);
            }finally {
                complete = true;
            }
        }
    }

    /**
     * 查询所有授权中心服务所在物理机ip
     * @return
     */
    private void setOauthServerAddressList(){
        try {
            List<ServiceInstance> serverAddressList = discoveryClient.getInstances(XSHI_CLOUD_OAUTH);
            if(CollectionUtil.isNotEmpty(serverAddressList)){//查询所有的客户端服务注册到nacos中心的时候 WEB服务自身所在的客户端IP
                List<String> list = new ArrayList<>();
                for(ServiceInstance serviceInstance : serverAddressList){
                    list.add(serviceInstance.getHost());
                }
                String result = list.stream().distinct().collect( Collectors.joining( "," ) );
                oauthClientConfig.setAddress(result);
                doChannel(list);
            }
        }catch (Exception e){
            log.info("查询授权中心服务所在ip异常：{}",e);
        }
    }

    /**
     * 处理新增节点 重新加载到监听器中
     * @param list
     */
    private void doChannel(List<String> list){
        Map<String, ChannelEntity> channelEntityMap = nettyClient.getChannelEntityList();
        List<String> newList = new ArrayList<>();
        if(CollectionUtil.isNotEmpty(channelEntityMap)){
            Iterator<Map.Entry<String, ChannelEntity>> it = channelEntityMap.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry<String, ChannelEntity> entry = it.next();
                ChannelEntity channelEntity = nettyClient.getChannelEntity(entry.getKey());
                if(null != channelEntity){
                    newList.add(channelEntity.getIp());
                }
            }
        }
        //判断集合一不在集合二中的数据
        List<String> ls = list.stream().filter(item->newList.stream().allMatch(each->!item.equals(each))).collect(Collectors.toList());
        String result = ls.stream().distinct().collect( Collectors.joining( "," ) );
        if(!StringUtil.isEmpty(result)){
            nettyClient.dynamicsLoad(result);
        }
    }
}
